<?php

namespace h5Api\behaviors;

use Carbon\Carbon;
use common\components\fast_api\ApiException;
use common\datas\Enums;
use common\Tools;
use h5Api\models\db\Users;
use yii\base\ActionFilter;

class TokenCheck extends ActionFilter
{
    /**
     * @param \yii\base\Action $action
     * @return bool
     * @throws
     */
    public function beforeAction($action)
    {
        $request = \Yii::$app->request;
        $params = $request->post();
        if (isset($params['token'])) {
            $this->_throwError(201808161402, 'token请在header里请求，否则会有安全隐患');
        }
        $token = $request->headers->get('authorization');
        $token = str_replace("Bearer ", "", $token);
        if (!$token) {
            $this->_throwError(201801010000, 'token未找到');
        }
        if (isset($params['key'])){
            $this->_throwError(201808161401, '请不要传key，会有安全隐患');
        }
        if (strlen($token) != 32) {
            $this->_throwError(201808161403, '认证口令长度错误');
        }else{
            $user = Users::findIdentityByAccessToken($token);
        }
        if (!$user){
            $this->_throwError(201808161455, "没有找到用户,请重新登陆");
        }
        if (\Yii::$app->params['isCheckTime']) {
            if (!isset($params['timestamp'])) {
                $this->_throwError(201808161406, '请求必须有当前操作时间戳');
            }
            if (strlen($params['timestamp']) != 10) {
                $this->_throwError(201808161407, '时间戳长度必须为10位秒数');
            }
            if (abs(substr($params['timestamp'], 0, 10) - Carbon::now()->timestamp) > 600){
                $this->_throwError(201808161408, '操作超时或时间异常，请检查设备时间');
            }
        }
        if (\Yii::$app->params['isCheckNonce']) {
            if (!isset($params['nonce'])) {
                $this->_throwError(201808161409, '请求必须设置随机数');
            }
            if (strlen($params['nonce']) < 9 || strlen($params['nonce']) > 181) {
                $this->_throwError(201808161411, '随机数长度错误');
            }
            $nonce_key = APP_ID.'/nonceUser/'.$user->id;
            $tmp_nonces = is_array(\Yii::$app->cache->get($nonce_key))?\Yii::$app->cache->get($nonce_key):[];
            if (!in_array($params['nonce'], $tmp_nonces)){
                $tmp_nonces[] = $params['nonce'];
                if (count($tmp_nonces) > 10000) {
                    array_shift($tmp_nonces);
                }
                \Yii::$app->cache->set($nonce_key, $tmp_nonces, 3600 * 25);
            }else{
                $this->_throwError(201808161412, '请求随机数重复');
            }
        }
        if (\Yii::$app->params['isCheckSign']) {
            if (!isset($params['sign'])) {
                $this->_throwError(201808161404, '请求必须有请求签名');
            }
            if (strlen($params['sign'])!=32) {
                $this->_throwError(201808161405, '请求签名长度错误');
            }
            $p = $params;
            $p['token'] = $user->token;
            $p['key'] = $user->key;
            ksort($p);
            unset($p['sign']);
            $p_str = Tools::toQuery($p);
            $_sign = md5($p_str);
            if ($_sign != $params['sign']){
                $this->_throwError(201808161457, "验签失败");
            }
        }
        if ($user->status != Enums::ACTIVE){
            $this->_throwError(201808161456, "用户状态异常，如果你被禁了，请联系管理员");
        }
        \Yii::$app->user->login($user);
        return parent::beforeAction($action);
    }

    private function _throwError($code, $msg, $status = 561)
    {
        \Yii::$app->response->headers->set('status', $status);
        throw new ApiException($code, $msg);
    }
}